<template>
  <div class="list">
    <el-container>
      <el-aside width="1000px">
        <el-row>
          <el-col :span="5">
            <div>
              <br />
              <span style="font-size: 20">路径</span>
              <el-divider></el-divider>
              <el-tree :data="list" :expand-on-click-node="false" :highlight-current="true" :default-expand-all="true"
                :props="defaultProps" @node-click="handleNodeClick"></el-tree>
            </div>
          </el-col>
          <el-col :span="19">
            <div>
              <el-row type="flex">
                <div>
                  <el-upload action="#" :http-request="upload" :before-upload="beforeUpload" :show-file-list="false">
                    <el-button type="primary" round>上传</el-button>
                  </el-upload>
                </div>
                <el-button round @click="add">新建文件夹</el-button>
                <el-col>
                  <el-button round @click="deleteById">删除文件夹</el-button></el-col>
              </el-row>
            </div>
            <div>
              <el-table v-loading="listLoading" :data="fileList" highlight-current-row
                @current-change="handleCurrentChange" max-height="350" style="width: 100%; margin-top: 4%">
                <el-table-column prop="fileName" label="文件名" width="180" />
                <el-table-column prop="size" label="文件大小" width="110" />
                <el-table-column prop="createTime" label="创建时间" />
                <el-table-column label="操作" align="center" fixed="right">
                  <template slot-scope="scope">
                    <el-row :gutter="20">
                      <el-col :span="6">
                        <i class="el-icon-download" @click="downloadFile(scope.row)"></i>
                      </el-col>
                      <el-col :span="6">
                        <i class="el-icon-share" @click="shareDialog(scope.row)"></i>
                      </el-col>
                      <el-col :span="6">
                        <i class="el-icon-edit" @click="edit(scope.row.fileId)"></i>
                      </el-col>
                      <el-col :span="6">
                        <i class="el-icon-delete" @click="removeDataById(scope.row.fileId)"></i>
                      </el-col>
                    </el-row>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </el-col>
        </el-row>

        <el-row style="margin-top: auto">
          <div>
            <el-divider content-position="left">上传列表</el-divider>
            <!-- 正在上传的文件列表 -->
            <div class="uploading" v-for="(uploadFile, index) in this.uploadFileList" :key="index">
              <span class="fileName">{{ uploadFile.fileName }}</span>
              <span class="fileSize">{{ formatSize(uploadFile.size) }}</span>

              <div class="parse">
                <span>解析进度： </span>
                <el-progress :text-inside="true" :stroke-width="16" :percentage="uploadFile.parsePercentage">
                </el-progress>
              </div>
              <div class="progress">
                <span>上传进度：</span>

                <el-progress :text-inside="true" :stroke-width="16" :percentage="uploadFile.uploadPercentage">
                </el-progress>
                <span v-if="(uploadFile.uploadPercentage > 0) &
                  (uploadFile.uploadPercentage < 100)
                  ">
                  <span class="uploadSpeed">{{ uploadFile.uploadSpeed }}</span>

                  <el-button circle link @click="changeUploadingStop(uploadFile)">
                    <el-icon size="20" v-if="uploadFile.uploadingStop == false">
                      <VideoPause />
                    </el-icon>
                    <el-icon size="20" v-else>
                      <VideoPlay />
                    </el-icon>
                  </el-button>
                </span>
              </div>
            </div>
          </div>
        </el-row>
      </el-aside>

      <el-container>
        <el-main>
          <div>
            <p>文件详情：</p>
            <el-row>
              <img
                src="https://tse1-mm.cn.bing.net/th/id/OIP-C.HPXe6JVS4jjTbs56av-1JQHaHa?w=198&h=198&c=7&r=0&o=5&dpr=1.1&pid=1.7" />
            </el-row>
            <el-row>
              <p>文件名称:{{ file.fileName }}</p>
            </el-row>
            <el-row>
              <p>创建时间:{{ file.createTime }}</p>
            </el-row>
            <el-row>
              <p>修改时间:{{ file.updateTime }}</p>
            </el-row>
            <el-row>
              <p>文件格式:{{ file.type }}</p>
            </el-row>
            <el-row>
              <p>文件大小:{{ file.size }}</p>
            </el-row>
          </div>
        </el-main>
      </el-container>
    </el-container>

    <el-dialog title="修改" :visible.sync="dialogVisible" width="40%">
      <el-form ref="dataForm" :model="file" label-width="100px" size="small" style="padding-right: 40px">
        <el-form-item label="文件名" prop="fileName">
          <el-input v-model="file.fileName" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
        <el-button type="primary" icon="el-icon-check" @click="update()" size="small">确 定</el-button>
      </span>
    </el-dialog>

    <el-dialog title="添加文件夹" :visible.sync="anotherDialogVisible" width="40%">
      <el-form ref="dataForm" :model="folder" label-width="100px" size="small" style="padding-right: 40px">
        <el-form-item label="文件夹名" prop="floderName">
          <el-input v-model="folder.folderName" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="anotherDialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
        <el-button type="primary" icon="el-icon-check" @click="save()" size="small">确 定</el-button>
      </span>
    </el-dialog>

    <div>
      <el-dialog title="分享" :visible.sync="dialogShow" width="30%">
        <span>
          <el-form :model="fileUrl" label-width="100px" @submit.prevent>

            <el-form-item label="文件"> {{ file.fileName }} </el-form-item>


            <el-form-item label="有效期">
              <el-radio-group v-model="fileUrl.type">
                <el-radio :label="0">1天</el-radio>
                <el-radio :label="1">7天</el-radio>
                <el-radio :label="2">30天</el-radio>
                <el-radio :label="3">永久有效</el-radio>
              </el-radio-group>
            </el-form-item>

            <el-form-item label="提取码">
              <el-radio-group v-model="codeType">
                <el-radio :label="0">自定义</el-radio>
                <el-radio :label="1">系统生成</el-radio>
              </el-radio-group>
            </el-form-item>

            <el-form-item prop="code" v-if="codeType == 0">
              <el-input clearable placeholder="请输入5位提取码" v-model.trim="fileUrl.code" maxLength="5"
                :style="{ width: '160px' }"></el-input>
            </el-form-item>
          </el-form>

        </span>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dialogShow = false">取 消</el-button>
          <el-button type="primary" @click="shareUrl()">确 定</el-button>
        </span>
      </el-dialog>

      <div>
        <el-dialog title="分享" :visible.sync="anotherDialogShow" width="30%">
          <span>
            <el-form :model="fileUrl" label-width="100px" @submit.prevent>
              <el-form-item label="文件"> {{ file.fileName }} </el-form-item>
              <el-form-item label="文件链接">
                <el-input :value="fileUrl.url"></el-input>
              </el-form-item>
              <el-form-item label="提取码">
                <el-input :value="fileUrl.code"></el-input>
              </el-form-item>
            </el-form>

          </span>
          <span slot="footer" class="dialog-footer">
            <el-button type="primary" @click="anotherDialogShow = false">确 定</el-button>
          </span>
        </el-dialog>
      </div>
    </div>
  </div>
</template>

<script>
import api from "@/api/system/folder";
import fileApi from "@/api/system/file";
import urlApi from "@/api/system/fileUrl";

import emitter from "@/utils/eventBus";
import SparkMD5 from "spark-md5";
import request from "@/utils/request";
export default {
  name: "folderList",
  data() {
    return {
      list: [],

      currentFolder: 0,
      defaultProps: {
        children: "children",
        label: "folderName",
      },
      fileList: [],
      listLoading: false,

      dialogVisible: false,
      file: {},

      anotherDialogVisible: false,
      folder: {},

      //分享文件
      dialogShow: false,
      anotherDialogShow: false,
      codeType: 1,
      fileUrl: {},

      //上传文件
      uploadFileList: [],
      parsePercentage: 0,
      uploadPercentage: 0,


      downloadingFileList: []
    };
  },
  created() {
    this.fetchData();
  },
  methods: {
    handleNodeClick(data) {
      this.currentFolder = data.folderId;
      fileApi.getByFolder(data.folderId).then((response) => {
        this.fileList = response.data;
      });
    },
    fetchData() {
      api.findNodes().then((response) => {
        this.list = response.data;
      });
    },
    edit(id) {
      this.dialogVisible = true;
      fileApi.getUserId(id).then((response) => {
        this.file = response.data;
      });
    },
    update() {
      fileApi.update(this.file).then((response) => {
        this.$message.success("操作成功");
        this.dialogVisible = false;

        this.handleNodeClick(this.file);
      });
    },
    removeDataById(id) {
      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        fileApi.removeById(id).then((response) => {
          //提示
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          //刷新
          fileApi.getByFolder(this.currentFolder).then((response) => {
            this.fileList = response.data;
          });
        });
      });
    },
    add() {
      this.anotherDialogVisible = true;
    },
    save() {
      this.folder.parentId = this.currentFolder;
      api.save(this.folder).then((response) => {
        this.$message.success("操作成功");
        this.anotherDialogVisible = false;

        this.fetchData();
      });
    },
    deleteById() {
      this.$confirm("此操作将永久删除该文件夹, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        api.deleteById(this.currentFolder).then((response) => {
          //提示
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          //刷新
          this.fetchData();
        });
      });
    },
    handleCurrentChange(data) {
      this.file = data;
    },

    formatSize(size) {
      //size的单位大小k
      var unit;
      var units = [" B", " K", " M", " G"];
      var pointLength = 2;
      while ((unit = units.shift()) && size > 1024) {
        size = size / 1024;
      }
      // return (
      //   (unit === "B"
      //     ? size
      //     : size.toFixed(pointLength === undefined ? 2 : pointLength)) + unit
      // );
      return size;
    },
    //计算文件的md5值
    computeMd5(file, uploadFile) {
      console.log("开始计算");
      return new Promise((resolve, reject) => {
        //分片读取并计算md5
        console.log("开始计算");
        const chunkTotal = 100; //分片数
        const chunkSize = Math.ceil(file.size / chunkTotal);
        const fileReader = new FileReader();
        const md5 = new SparkMD5();
        let index = 0;
        const loadFile = (uploadFile) => {
          uploadFile.parsePercentage = parseInt((index / file.size) * 100);
          const slice = file.slice(index, index + chunkSize);
          fileReader.readAsBinaryString(slice);
        };
        console.log("计算完成");
        loadFile(uploadFile);
        fileReader.onload = (e) => {
          md5.appendBinary(e.target.result);
          if (index < file.size) {
            index += chunkSize;
            loadFile(uploadFile);
          } else {
            // md5.end() 就是文件md5码
            resolve(md5.end());
          }
        };
      });
    },
    //检查文件是否存在
    checkFile(md5) {
      console.log("checkMd5");
      return request({
        url: "/common/check",
        method: "get",
        params: {
          md5: md5,
        },
      });
    },

    //文件上传之前,el-upload自动触发
    async beforeUpload(file) {
      console.log("2.上传文件之前");
      var uploadFile = {};
      uploadFile.name = file.name;
      uploadFile.size = file.size;
      uploadFile.parsePercentage = this.parsePercentage;
      uploadFile.uploadPercentage = this.uploadPercentage;
      uploadFile.uploadSpeed = "0 M/s";
      uploadFile.chunkList = null;
      uploadFile.file = file;
      uploadFile.uploadingStop = false;
      this.uploadFileList.push(uploadFile);
      console.log(this.uploadFileList);
      console.log("获得md5");

      var md5 = await this.computeMd5(file, uploadFile); //async 和 await配可以实现等待异步函数计算完成
      console.log("获得md5:" + md5);
      console.log("后面");
      uploadFile.md5 = md5;

      var res = await this.checkFile(md5); //上传服务器检查，以确认是否秒传
      var data = res.data;
      console.log(data);
      if (!data.isUploaded) {
        uploadFile.chunkList = data.chunkList;
        uploadFile.needUpload = true;
      } else {
        uploadFile.needUpload = false;
        uploadFile.uploadPercentage = 100;

        console.log("文件已秒传");
        ElMessage({
          showClose: true,
          message: "文件已秒传",
          type: "warning",
        });
      }
    },
    //点击暂停或开始上传
    changeUploadingStop(uploadFile) {
      uploadFile.uploadingStop = !uploadFile.uploadingStop;
      if (!uploadFile.uploadingStop) {
        this.uploadChunk(uploadFile.file, 1, uploadFile);
      }
    },
    //上传文件,替换el-upload的action
    upload(xhrData) {
      var uploadFile = null;

      for (var i = 0; i < this.uploadFileList.length; i++) {
        if (
          (xhrData.file.name == this.uploadFileList[i].name) &
          (xhrData.file.size == this.uploadFileList[i].size)
        ) {
          uploadFile = this.uploadFileList[i];

          break;
        }
      }

      if (uploadFile.needUpload) {
        console.log("3.上传文件");

        // 分片上传文件
        // 确定分片的大小
        this.uploadChunk(xhrData.file, 1, uploadFile);
      }
    },
    //上传文件分片
    uploadChunk(file, index, uploadFile) {
      console.log("上传分片");
      var chunkSize = 1024 * 1024 * 10; //10mb
      var chunkTotal = Math.ceil(file.size / chunkSize);
      if (index <= chunkTotal) {
        // 根据是否暂停，确定是否继续上传

        // console.log("4.上传分片");

        var startTime = new Date().valueOf();

        var exit = uploadFile.chunkList.includes(index);
        // console.log("是否存在",exit);

        if (!exit) {
          //    console.log("3.3上传文件",uploadingStop);
          if (!uploadFile.uploadingStop) {
            // 分片上传，同时计算进度条和上传速度
            // 已经上传的不在上传、
            // 上传完成后提示，上传成功
            // console.log("上传分片1",index);
            var form = new FormData();
            var start = (index - 1) * chunkSize;
            let end =
              index * chunkSize >= file.size ? file.size : index * chunkSize;
            let chunk = file.slice(start, end);
            //  downloadBlob(chunk,file)
            //  console.log("chunk",chunk);
            console.log(file);
            form.append("chunk", chunk);
            form.append("index", index);
            form.append("chunkTotal", chunkTotal);
            form.append("chunkSize", chunkSize);
            form.append("md5", uploadFile.md5);
            form.append("fileSize", file.size);
            form.append("fileName", file.name);
            form.append("folderId", this.currentFolder);
            // console.log("上传分片", index);

            request({
              url: "/common/chunk",
              method: "post",
              data: form,
            }).then((res) => {
              var endTime = new Date().valueOf();
              var timeDif = (endTime - startTime) / 1000;
              // console.log("上传文件大小",formatSize(chunkSize));
              // console.log("耗时",timeDif);
              // console.log("then",index);

              // uploadSpeed = (chunkSize/(1024*1024))  / timeDif +" M / s"

              // uploadFile.uploadSpeed = (10 / timeDif).toFixed(1) + " M/s";
              uploadFile.uploadSpeed = 10 / timeDif + " M/s";
              // console.log(res.data.data);
              //  console.log("f2",uploadFile);
              uploadFile.chunkList.push(index);
              //  console.log("f3",uploadFile);

              uploadFile.uploadPercentage = parseInt(
                (uploadFile.chunkList.length / chunkTotal) * 100
              );
              // console.log("上传进度",uploadFile.uploadPercentage);

              if (index == chunkTotal) {
                emitter.emit("reloadFileList");
              }

              this.uploadChunk(file, index + 1, uploadFile);
            });
          }
        } else {
          uploadFile.uploadPercentage = parseInt(
            (uploadFile.chunkList.length / chunkTotal) * 100
          );

          this.uploadChunk(file, index + 1, uploadFile);
        }
        // }
      }
      fileApi.getByFolder(this.currentFolder).then((response) => {
        this.fileList = response.data;
      });
    },

    //下载文件
    formatSize(file) {
      //console.log("size",file.size);
      var size = file.size;
      var unit;
      var units = [" B", " K", " M", " G"];
      var pointLength = 2;
      while ((unit = units.shift()) && size > 1024) {
        size = size / 1024;
      }
      return (
        (unit === "B"
          ? size
          : parseFloat(size).toFixed(pointLength === undefined ? 2 : pointLength)) + unit
      );
    },
    changeDownloadStop(file) {
      file.downloadingStop = !file.downloadingStop;
      if (!file.downloadingStop) {
        console.log("开始。。");
        this.downloadChunk(1, file);
      }
    },

    downloadFile(file) {

      console.log("下载", file);
      file.downloadingStop = false;
      file.downloadSpeed = "0 M/s";
      file.downloadPersentage = 0;
      file.blobList = [];
      file.chunkList = [];
      this.downloadingFileList.push(file);

      this.downloadChunk(1, file);
    },

    downloadChunk(index, file) {
      var chunkSize = 1024 * 1024 * 5;
      var chunkTotal = Math.ceil(file.size / chunkSize);
      console.log(file);
      if (index <= chunkTotal) {
        // console.log("下载进度",index);
        var exit = file.chunkList.includes(index);
        // console.log("存在", exit);

        if (!exit) {
          if (!file.downloadingStop) {
            var formData = new FormData();
            formData.append("fileName", file.fileName);
            formData.append("md5", file.md5);
            formData.append("chunkSize", chunkSize);
            formData.append("index", index);
            formData.append("chunkTotal", chunkTotal);
            if (index * chunkSize >= file.size) {
              chunkSize = file.size - (index - 1) * chunkSize;
              formData.set("chunkSize", chunkSize);
            }

            var startTime = new Date().valueOf();

            request({
              url: "/common/download",
              method: "post",
              data: formData,
              responseType: "blob",
              timeout: 50000,
            }).then((res) => {

              console.log("开始下载第" + index + "个分片");

              file.chunkList.push(index);

              var endTime = new Date().valueOf();
              var timeDif = (endTime - startTime) / 1000;
              file.downloadSpeed = 5 / timeDif + " M/s";
              //todo
              file.downloadPersentage = parseInt((index / chunkTotal) * 100);
              // var chunk = res.data.data.chunk
              // const blob = new Blob([res.data]);
              const blob = res;
              file.blobList.push(blob);
              console.log(file.blobList);
              if (index == chunkTotal) {
                var resBlob = new Blob(file.blobList, {
                  type: "application/octet-stream",
                });
                console.log("resb", resBlob);

                let url = window.URL.createObjectURL(resBlob); // 将获取的文件转化为blob格式
                console.log(url);
                let a = document.createElement("a"); // 此处向下是打开一个储存位置
                a.style.display = "none";
                a.href = url;
                // 下面两行是自己项目需要的处理，总之就是得到下载的文件名（加后缀）即可

                var fileName = file.fileName;
                console.log("down" + file.fileName);
                a.setAttribute("download", fileName);
                document.body.appendChild(a);
                a.click(); //点击下载
                document.body.removeChild(a); // 下载完成移除元素
                window.URL.revokeObjectURL(url); // 释放掉blob对象
              }

              this.downloadChunk(index + 1, file);
            });
          }
        } else {
          file.downloadPersentage = parseInt((index / chunkTotal) * 100);
          this.downloadChunk(index + 1, file);
        }
      }
    },


    
    shareDialog(file) {
      this.fileUrl = {}
      this.dialogShow = true
      this.fileUrl.fileId = file.fileId
    },
    shareUrl() {
      if (this.codeType == 1) {
        var t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",
          a = t.length,
          n = "";
        for (let i = 0; i < 5; i++) n += t.charAt(Math.floor(Math.random() * a));
        this.fileUrl.code = n;
        console.log(this.fileUrl.code)
      }
      urlApi.share(this.fileUrl).then(response => {
        this.fileUrl = response.data
      })
      this.dialogShow = false
      this, this.anotherDialogShow = true
    }
  }
};
</script>